/**
 * 
 */
package com.lorizz.picpub.web.controller.impl;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;

import com.lorizz.picpub.query.UpmQueries;
import com.lorizz.picpub.web.Constants;
import com.lorizz.picpub.web.TokenGenerator;
import com.lorizz.picpub.web.controller.UserProfileController;
import com.lorizz.upm.UserProfile;
import com.lorizz.upm.np.NPUtils;
import com.lorizz.upm.np.UserProfileNP;
import com.lorizz.upm.repository.Repository;

/**
 * @author wind hong
 * 
 */
public class UserProfileControllerImpl implements UserProfileController {

	private Repository upmRepository;
	private TokenGenerator tokenGenerator;
	private String cookieName = "ut";
	private static String REGEXP_EMAIL = "^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
	private Pattern emailPattern = Pattern.compile(REGEXP_EMAIL, Pattern.CASE_INSENSITIVE);

	public void setUpmRepository(Repository upmRepository) {
		this.upmRepository = upmRepository;
	}

	public void setTokenGenerator(TokenGenerator tokenGenerator) {
		this.tokenGenerator = tokenGenerator;
	}

	public void setCookieName(String cookieName) {
		this.cookieName = cookieName;
	}

	private void saveUserProfileToSession(HttpSession session, UserProfileNP userProfile) {
		session.setAttribute(Constants.SESSION_USERPROFILE, userProfile);
	}

	@Override
	public String signIn(Model model) {
		model.addAttribute("name", "");
		return "signin";
	}

	@Override
	public String signUp(Model model) {
		model.addAttribute("userProfile", new UserProfileNP());
		return "signup";
	}

	@Override
	public String signIn(String name, String pincode, String remember, String path, HttpSession session,
			HttpServletResponse response, Model model) {
		List<UserProfile> result = upmRepository.executeQuery(UpmQueries.instance().userProfiles(name, md5(pincode)));
		if (result.isEmpty()) {
			model.addAttribute("name", name);
			return "signin";
		}
		UserProfile userProfile = result.get(0);
		if (remember != null) {
			String token = tokenGenerator.generate(userProfile);
			Cookie utCookie = new Cookie(cookieName, token);
			utCookie.setPath("/");
			utCookie.setMaxAge(Integer.MAX_VALUE);
			response.addCookie(utCookie);
		}
		UserProfileNP userProfileNP = NPUtils.packageUserProfile(userProfile);
		saveUserProfileToSession(session, userProfileNP);
		if (path != null && path.length() > 0)
			return "redirect:" + path;
		return "redirect:/i/albums";
	}

	@Override
	public String signUp(UserProfileNP userProfileNP, BindingResult result, HttpSession session, Model model) {
		validate(userProfileNP, result);
		if (result.hasErrors()) {
			return "signup";
		}
		UserProfile userProfile = upmRepository.createUserProfile();
		userProfile.setName(userProfileNP.getName());
		userProfile.setEmail(userProfileNP.getEmail());
		userProfile.setPassword(md5(userProfileNP.getPassword()));
		userProfile = upmRepository.persist(userProfile);
		userProfileNP.setId(userProfile.getId());
		saveUserProfileToSession(session, userProfileNP);
		return "redirect:/i/albums";
	}

	private void validate(UserProfileNP userProfile, Errors errors) {
		ValidatorUtils.NotEmpty("name", userProfile.getName(), errors, "signup.error.name.empty");
		ValidatorUtils.NotEmpty("password", userProfile.getPassword(), errors, "signup.error.password.empty");
		ValidatorUtils.NotEmpty("email", userProfile.getEmail(), errors, "signup.error.email.empty");
		if (userProfile.getEmail() != null) {
			if (!emailPattern.matcher(userProfile.getEmail()).matches()) {
				errors.rejectValue("email", "signup.error.email.invalid");
			}
		}
		if (userProfile.getName() != null) {
			List<UserProfile> result = upmRepository.executeQuery(UpmQueries.instance().userProfiles(
					userProfile.getName()));
			if (!result.isEmpty()) {
				errors.rejectValue("name", "signup.error.name.exist");
			}
		}
	}

	private String md5(String input) {
		try {
			byte[] bytes = input.getBytes("UTF-8");
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] digested = md.digest(bytes);
			StringBuilder hexValue = new StringBuilder();
			for (int i = 0; i < digested.length; i++) {
				int val = ((int) digested[i]) & 0xff;
				if (val < 16)
					hexValue.append("0");
				hexValue.append(Integer.toHexString(val));
			}
			return hexValue.toString();
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public String logout(HttpSession session, HttpServletResponse response, Model model) {
		session.invalidate();
		Cookie utCookie = new Cookie(cookieName, "");
		utCookie.setPath("/");
		utCookie.setMaxAge(0);
		response.addCookie(utCookie);
		return "redirect:/signin";
	}

}
